/*
 * EntranceDoorAPI.h
 *
 *  Created on: Jul 23, 2013
 *      Author: m
 */

#ifndef ENTRANCEDOORAPI_H_
#define ENTRANCEDOORAPI_H_

#include <vector>
#include "application_common.h"
#include "messages.h"
#include "Visitor.h"
#include "ConcurrentMessageQueue.h"

namespace application
{

struct DoorReply
{
    bool m_success;
    SerializedTicket m_ticket;
};

class EntranceDoorAPI
{
protected:

public:
    EntranceDoorAPI(){}
    virtual ~EntranceDoorAPI(){}

    std::vector<DoorPass> getAvaliaveDoors()
    {
        std::vector<DoorPass> avaliableDoors;

        // TODO: Completar método para hacerlo escalable

        avaliableDoors.push_back( DoorPass( "entrance1", "entrance1.request" ) );
        avaliableDoors.push_back( DoorPass( "entrance2", "entrance2.request" ) );

        return avaliableDoors;
    }

    bool enter( DoorPass doorPass, Visitor &visitor )
    {
        bool result;
        EntranceRequest request;
        communication::ConcurrentMessageQueue<EntranceRequest> requestQueue( doorPass.m_doorAddress );

        /*
         * Genero la cola por la que voy a escuchar la respuesta de la puerta
         */
        std::string replyQueueName( visitor.getId() + "." + doorPass.m_doorName );
        communication::ConcurrentMessageQueue<DoorReply> replyQueue( replyQueueName );


        /*
         * Asigno el Door pass al visitante
         *
         * Simplemente lo seteo para mantener un historial y a lo sumo hacer alguna
         *  verificación del lado d ela puerta de entrada
         */
        visitor.getTicket().m_entrancePass = doorPass;

        /*
         * Envio el pedido del visitante a la puerta
         */
        request.m_visitor = visitor.serialize();
        request.m_replyTo = replyQueueName;
        requestQueue.put( request );

        /*
         * Espero la respuesta de la puerta
         */
        DoorReply reply = replyQueue.get();

        /*
         * Analizo la respuesta y respondo según el resultado
         */

        if ( reply.m_success )
        {
            visitor.setTicket( Ticket( reply.m_ticket ) );
            result = true;
        }
        else
        {
            result = false;
        }

        return result;
    }

    bool enterStub( DoorPass doorPass, Visitor &visitor )
    {
        visitor.getTicket().m_entrancePass = doorPass;

        BusStationPass pass;

        if ( doorPass.m_doorName.compare( "entrance1" ) == 0 )
        {
            pass.m_busStationName = "busStation1";
        }
        if ( doorPass.m_doorName.compare( "entrance2" ) == 0 )
        {
            pass.m_busStationName = "busStation2";
        }

        pass.m_busStationAddress = BUS_STATION_REQUEST_BASENAME + pass.m_busStationName;

        visitor.getTicket().m_entranceBusStationPass = pass;

        return true;
    }
};

} /* namespace physical */
#endif /* ENTRANCEDOORAPI_H_ */
